﻿using System.Collections.Generic;
using UnityEngine;
using System;

namespace UFrameWork
{
    /// <summary>
    /// 计时器类
    /// </summary>
    public class Timer : MonoBehaviour
    {
        /// <summary>
        /// 是否已初始化
        /// 在线程中判断使用
        /// </summary>
        public static bool IsInit { get { return mTimer != null; } }

        /// <summary>
        /// 计时器id生成器
        /// </summary>
        private static uint UpdateID = 0;

        /// <summary>
        /// 实例对象
        /// </summary>
        private static Timer mTimer;

        private List<TimerData> mWait = new List<TimerData>();

        void Awake()
        {
            if (mTimer != null)
            {
                Destroy(gameObject);
            }
        }

        void Update()
        {

            lock (mWait)
            {
                if (mWait.Count == 0) return;
                for (int i = 0; i < mWait.Count; i++)
                {
                    if (mWait[i] == null)
                    {
                        mWait.RemoveAt(i);
                        i--;
                        continue;
                    }

                    if (DateTime.Now.Ticks < mWait[i].time)
                    {
                        continue;
                    }

                    try
                    { 
                        if(mWait[i].func != null) mWait[i].func();
                    }
                    catch(Exception e)
                    {
                        ULog.Error(e);
                    }
                    mWait.RemoveAt(i);
                    i--;
                }
            }
        }

        public uint Add(float time, Action func, string flag)
        {
            TimerData data = new TimerData();
            data.id = ++UpdateID;
            data.time = DateTime.Now.Ticks + (long)(time * 10000000);
            data.func = func;
            data.flag = flag;
            lock (mWait)
            {
                mWait.Add(data);
            }
            return data.id;
        }


        /// <summary>
        /// 等待后执行函数
        /// </summary>
        public static uint Wait(float time, Action func,string flag = "null")
        {
            if (mTimer == null)
            {
                Init();
            }
            return mTimer.Add(time, func, flag);
        }

        /// <summary>
        /// 终止计时器
        /// 0终止所有计时器
        /// </summary>
        public static void Kill(uint id = 0)
        {
            if (mTimer == null)
            {
                Init();
                return;
            }
            
            lock(mTimer.mWait)
            {
                for (int i = mTimer.mWait.Count - 1; i >= 0; i--)
                {
                    if (mTimer.mWait[i].id == id || id == 0)
                    {
                        mTimer.mWait.RemoveAt(i);
                    }
                }
            }
        }

        /// <summary>
        /// 按标记杀死计时器
        /// Empty 删除所有
        /// </summary>
        /// <param name="flag"></param>
        public static void FlagKill(string flag = "")
        {
            if (mTimer == null)
            {
                Init();
                return;
            }

            lock (mTimer.mWait)
            {
                for (int i = mTimer.mWait.Count - 1; i >= 0; i--)
                {
                    if (mTimer.mWait[i].flag == flag || string.IsNullOrEmpty(flag))
                    {
                        mTimer.mWait.RemoveAt(i);
                    }
                }
            }
        }

        /// <summary>
        /// 实例化计时器对象
        /// </summary>
        public static void Init()
        {
            if (mTimer == null)
            {
                GameObject obj = new GameObject("Timer");
                obj.hideFlags = HideFlags.HideInHierarchy;
                DontDestroyOnLoad(obj);
                mTimer = obj.AddComponent<Timer>();
            }
        }

        private class TimerData
        {
            /// <summary>
            /// 计时器id
            /// 用于终止计时器使用
            /// </summary>
            public uint id;

            /// <summary>
            /// 计时器类别标记
            /// </summary>
            public string flag;

            public long time;

            public Action func;
        }
    }
}